import 'package:built_collection/built_collection.dart';
import 'package:backend.core/core/domain/entities/web/web_purchased_subscription_transaction.dart';
import 'package:backend.core/core/domain/entities/web/web_subscription_duration.dart';

abstract class GetWebPurchasedSubscriptionTransactionExpirationTimeMap {
  BuiltMap<String, DateTime> call({
    required BuiltList<WebPurchasedSubscriptionTransaction> transactions,
    required WebSubscriptionDuration subscriptionDuration,
    required bool test,
  });
}

class GetWebPurchasedSubscriptionTransactionExpirationTimeMapImpl
    implements GetWebPurchasedSubscriptionTransactionExpirationTimeMap {
  const GetWebPurchasedSubscriptionTransactionExpirationTimeMapImpl();

  @override
  BuiltMap<String, DateTime> call({
    required BuiltList<WebPurchasedSubscriptionTransaction> transactions,
    required WebSubscriptionDuration subscriptionDuration,
    required bool test,
  }) {
    late final Duration _subscriptionDuration;

    if (subscriptionDuration == WebSubscriptionDuration.month) {
      if (test) {
        _subscriptionDuration = const Duration(minutes: 5);
      } else {
        _subscriptionDuration = const Duration(days: 30);
      }
    } else if (subscriptionDuration == WebSubscriptionDuration.year) {
      if (test) {
        _subscriptionDuration = const Duration(minutes: 30);
      } else {
        _subscriptionDuration = const Duration(days: 365);
      }
    }

    final sortedTransactions = transactions.rebuild((transactions) {
      transactions.sort((first, second) {
        return first.time.compareTo(second.time);
      });
    });

    final expirationTimeMap = <String, DateTime>{};
    DateTime? lastUnrevokedTransactionExpirationTime;

    for (final transaction in sortedTransactions) {
      final Duration overlappingDuration;

      if (lastUnrevokedTransactionExpirationTime != null &&
          transaction.time.isBefore(lastUnrevokedTransactionExpirationTime)) {
        overlappingDuration = lastUnrevokedTransactionExpirationTime.difference(transaction.time);
      } else {
        overlappingDuration = Duration.zero;
      }

      final expirationTime = transaction.time.add(_subscriptionDuration).add(overlappingDuration);

      if (!transaction.revoked) {
        lastUnrevokedTransactionExpirationTime = expirationTime;
      }

      expirationTimeMap[transaction.id] = expirationTime;
    }

    return expirationTimeMap.build();
  }
}
